package com.jdbc.transaction;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
 * JDBC Part2 数据库事务
 * Description: 转账业务类
 *
 * Connection 方法：
 * 1. connection.setAutoCommit(false) 关闭事务自动提交，开启事务
 * 2. connection.commit() 手动提交事务
 * 3. connection.rollback() 事务回滚
 * 4. connection.close() 连接关闭
 *
 * TODO：
 *  1. 业务侧实现JDBC注册驱动、创建连接、DAO层方法调用、连接关闭。DAO层封装数据库操作方法。
 *  2. 事务开启与关闭，需要关闭事务的自动提交，手动调用方法提交事务。
 *  3. 事务执行代码用 try 包围，在 catch 执行回滚，在 finally 执行关闭连接。
 *  4. 相同的事务操作必须在一个Connection中。
 */
public class BankService {

    /**
     * 转账业务方法
     * 数据库中的金额字段数据类型设置为非负数，转账业务单一执行会报错，需要在事务中执行
     *
     * @param addAccount  加钱账号
     * @param subAccount  减钱账号
     * @param money  金额
     */
    public void transfer(String addAccount, String subAccount, int money) throws ClassNotFoundException, SQLException {

        System.out.println("addAccount = " + addAccount + ", subAccount = " + subAccount + ", money = " + money);

        // 1. 注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");

        // 2. 获取连接
        Connection connection = DriverManager.getConnection("jdbc:mysql:///jdbc", "root", "root");

        // 转账成功标记
        int flag = 0;

        //利用try代码块,开启事务，调用dao
        try {
            //开启事务(关闭事务自动提交)
            connection.setAutoCommit(false);

            //调用DAO层的加钱、减钱方法
            BankDao bankDao = new BankDao();
            bankDao.addMoney(addAccount, money, connection);
            System.out.println("--------------");
            // 业务传递的connection和加钱是同一个，才可以在一个事务中
            bankDao.subMoney(subAccount, money, connection);

            // 更新转账成功标记
            flag = 1;

            //不报错,提交事务
            connection.commit();
        } catch (Exception e) {
            //报错回滚事务
            connection.rollback();
            throw e;
        } finally {
            // 统一进行连接关闭
            connection.close();
        }

        if (flag == 1){
            System.out.println("转账成功!");
        }else{
            System.out.println("转账失败!");
        }
    }

}
